<?php

function format_text( $text ) {
  return "\n<p>\n" . preg_replace( "/\n\s*\n/", "\n</p>\n\n<p>\n", $text ) . "\n</p>\n";
}

/**
 *
 * @param $r
 * @return Publication
 */
function publication_construct( $source ) {
  if ( is_int( $source ) ) {
    $sql = "SELECT * FROM `posts` WHERE `id`=':1' ";
    $source = db::q($sql, $source)->assoc();
  }
  switch ( $source['type'] ) {
    case 'static':
      return new PStatic( $source );
    case 'news':
      return new PNews( $source );
    default:
      return new PArticle( $source );
  }
}

/**
 *
 * @param string $permalink
 * @param int $date
 * @return Publication
 */
function publication_find( $permalink, $date=0 ) {
  if ( $date ) {
    $date = explode( '.', $date );
    $d1 = mktime( 0, 0, 0, $date[0]+0, 1, $date[1]+0 );
    $d2 = mktime( 0, 0, 0, $date[0]+1, 1, $date[1]+0 );
    $sql = "SELECT * FROM `posts` WHERE `date`>=':1' AND `date`<':2' AND `permalink`=':3'";
    return publication_construct( db::q( $sql, $d1, $d2, $permalink )->assoc() );
  } else {
    $sql = "SELECT `posts`.`id`,`posts`.`type`,`posts`.`title`,`posts`.`text`,`posts`.`meta`,`posts`.`date`,`posts`.`permalink`,  `menu`.`ident` as `cat`
     FROM `posts`
     LEFT JOIN `menu`
       ON ( `menu`.`id`=`posts`.`meta` )
     WHERE `permalink`=':1'";
    return publication_construct( db::q( $sql, $permalink )->assoc());
  }
}
  
  


abstract class Publication extends ListElement {
  
  public $text       = '';
  public $title      = '';
  public $cat         = '';
  public $date       = 1234567890;
  public $permalink  = '';
  public $template   = '';
  protected $id      = 0;
  public $meta    = '';
  protected $type    = 'generic';
  
  
  public function __construct( $source = null ) {
    if ( $source === null || $source === 0 ) {
      $this->date = time();
      return;
    }
    if ( isset($source['id']) )
      $this->id         = $source['id'];
    if ( isset($source['text']) )
      $this->text       = $source['text'];
    if ( isset($source['type']) )
      $this->type       = $source['type'];
    if ( isset($source['title']) )
      $this->title      = $source['title'];
    if ( isset($source['meta']) )
      $this->meta       = $source['meta'];
    if ( isset($source['cat']) )
      $this->cat        = $source['cat'];
      if ( isset($source['permalink']) )
      $this->permalink  = $source['permalink'];
    $this->date = isset($source['date']) ? $source['date'] : time();
  }
  

  public function get_plain() {
    return $this->text;
  }
  
  
  public function get_id() {
    return $this->id;
  }
  
  
  
  public function get_linkdate() {
    return date( 'm.Y', $this->date );
  }
  
  
  public function get_formatted() {
    return "\n<p>\n" . str_replace( "\n", "\n</p>\n<p>\n", $this->text ) . "\n</p>\n";
  }
  
  public function save() {
    if ( $this->id ) {
      $sql = "
      UPDATE `posts`
        SET `title`     = ':1',
            `text`      = ':2',
            `meta`      = ':3',
            `type`      = ':4',
            `date`      = ':5',
            `permalink` = ':6'
      WHERE `id` = '" . $this->id . "' ";
    } else {
      $sql = "
      INSERT INTO `posts`
      ( `title`, `text`, `meta`, `type`, `date`, `permalink` )
      VALUES
      ( ':1', ':2', ':3', ':4', ':5', ':6' )
      ";
    }
    db::q( $sql, $this->title, $this->text, $this->meta, $this->type, $this->date, $this->permalink );
    if ( !$this->id ) {
      $this->id = db::inserted();
    }
  }
  
  
  
  public function tags( $param=null ) {
    if ( is_string($param) ) {
      // param is string
      // rewriting set of tags
      $t = explode( ',', $param ); //array of tag names
      array_walk( $t, create_function('&$v,$k', '$v = trim($v);') );
      //find already assigned tags
      $sql  = "
             SELECT `tags_nm`.`id`, `tags_nm`.`name`, `tags_nm`.`permalink`
               FROM `tags_names`
             INNER JOIN `tags`
               ON ( `tags_names`.`tag` = `tags`.`id` )
             INNER JOIN `tags_relat`
               ON ( `tags_names`.`id` = `tags_relat`.`tag` )
             INNER JOIN `tags_names` AS `tags_nm`
               ON ( `tags_nm`.`tag` = `tags`.`id` )
             WHERE `tags_relat`.`post` = ':1'
 ";
      $tags = db::q( $sql, $this->id )->arr();
      $tg = array(); // array for search by index
      if ( $tags )
      foreach ( $tags as $k => $v ) {
        $tg[$k] = $v['name'];
      }
      // query to add relation
      $query = "
            INSERT INTO `tags_relat`
            ( `tag`, `post` )
            VALUES
            ( ':1', ':2' )";
      foreach ( $t as $k => $v ) {
        // tag must not be empty
        if ( empty( $v ) ) continue;
        // permalink
        $p = str_replace(" ","_",$v);

        $key = array_search( $v, $tg );
        if ( $key === false ) {
          // not assigned to this post yet
          array_push( $tg, $v );
          $sql = "
              SELECT `id` FROM `tags_names`
              WHERE `permalink`=':1'";
          if ( !( $id = db::q($sql, $p)->get('id') ) ) {
            // does not exit, gotta be created
            $id = db::q( "SELECT MAX(`id`) AS `max` FROM `tags_names`" )->get('max')+1;
            $sql = "  INSERT INTO `tags_names` (`id`, `name`, `permalink`, `tag`)
                     VALUES (':1', ':2', ':3', ':1')               ;;
                     INSERT INTO `tags` (`id`, `name`) VALUES (':1', ':1')
                     ";
            db::q($sql, $id, $v, $p);
          }
          db::q($query, $id, $this->id);
        } else {
          // already assigned, must be saved
          unset($tags[$key]);
        }
      }
      unset($t,$tg);
    
      $sql = "DELETE FROM `tags_relat` WHERE `post`='" . $this->id . "' AND ( 0";
      // delete assigned tags, that still exist in $tags
      if ( $tags )
      foreach ( $tags as $k => $v ) {
        $sql .= " OR `tag`='" . $v['id'] . "'";
      }
      $sql .= " ) ";
      db::q($sql);
    } else {
      // show tags to user
      
    $sql = "SELECT `tags_names`.`name`, `tags_names`.`permalink`
              FROM `tags_names`
            INNER JOIN `tags_relat`
              ON ( `tags_names`.`id` = `tags_relat`.`tag` )
            WHERE `tags_relat`.`post` = ':1'
            ORDER BY `name`";
    $res = db::q( $sql, $this->id );
  
    $t = array();
    while ( $r = $res->assoc() ) {
      if ( $param === true ) {
        $t[] = $r['name'] ;
      } else {
        $t[] = '<a href="/tag/' . $r['permalink'] . '/">' . $r['name'] . '</a>';
      }
    }
    return implode ( ', ', $t );
    }
  }

  
  public function get_html( $cut=false ) {
    parent::get_html();
  }
  
  
}


class PArticle extends Publication {
  protected $type  = 'article';
  public $template = 'single_post';
    
  public function get_html( $cut=false  ) {
    if ( $this->id ) {
      $res = new Template( $this->template );
      $res->ins( 'text',       $this->get_formatted() );
      $res->ins( 'tags',       $this->get_tags() );
      $res->ins( 'meta',       $this->get_tags() );
      $res->ins( 'title',      $this->title );
      $res->ins( 'permalink',  $this->permalink );
      $res->ins( 'linkdate',   $this->get_linkdate() );
    } else {
      $res = new Template();
      $res->html = '<h1>Post not found.</h1>';
    }
    return $res;
  }
  
  
}



class PStatic extends Publication {
  protected $type  = 'static';
  public $template = 'static';
  
  public function get_html() {
    $tmp = new Template( $this->template );
    $tmp->assign( 'p', $this );
    return $tmp;
  }
}


class PNews extends Publication {
  protected $type  = 'news';
  public $template = 'news';
  
  public function get_html() {
    $tmp = new Template( $this->template );
    $tmp->assign( 'p', $this );
    return $tmp;
  }
}




class Pub_List {
  public $sql = "";
  public $num = 10;
  public $page = 1;
  public $template = null;
  
  private $item = array();
  
  public function load( $q = null ) {
    $item = array();
    if ( $q !== null ) {
      $this->sql = $q;
    }
    $offset = ($this->page - 1) * $this->num;
    $res = db::q( $this->sql." LIMIT ".$offset.",".$this->num );
    while ( $r = $res->assoc() ) {
      $this->item[] = publication_construct( $r );
    }
  }
  
  public function get_html( $cut=false ) {
    $html = new Template($this->template);
    $n = count( $this->item );
    foreach ( $this->item as &$post ) {
      $html->add( 'post', $post );
    }
    return $html;
  }
  
  
  /**
   * Get item at $index
   * @param $index int
   * @return Publication
   */
  public function &at( $index ) {
    return $this->item[$index];
  }
  
  
  function page_nav( $link ) {
    // заменяем поля выборки на количество
    $sql = preg_replace( "/SELECT (?(?<=FRO)[^M]|.)* FROM/", 'SELECT COUNT(*) AS `num` FROM', $this->sql );
    // сортировка не важна
    $sql = preg_replace( "/ORDER BY .* (A|DE)SC/", '', $sql );
    // количество страниц
    $n = ceil ( db::q( $sql )->get( 'num' ) / $this->num);
    
    // складываем номера страниц в $text
    $text = '';
    for ( $i = 1 ; $i <= $n ; $i++ ) {
      $text .= $i == $this->page ? $i : '
      <a href="' . $link . $i . '/">' . $i . '</a>';
    }
    return $text;
  }

}




?>